﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thrift.Transport;
using Thrift.Protocol;
using System.Reflection;

namespace System.Data.Cassandra.Extensions
{
    public static class CassandraClientExtensions
    {
        public static string HostName(this Apache.Cassandra.Cassandra.Client client)
        {
            string result;
            if (client == null)
            {
                result = null;
            }
            else
            {
                result = (client.InputProtocol.HostName() ?? client.OutputProtocol.HostName());
            }
            return result;
        }

        public static string HostName(this TProtocol protocol)
        {
            string result;
            if (protocol == null)
            {
                result = null;
            }
            else
            {
                TSocket tSocket = protocol.Transport.GetTSocket();
                if (tSocket != null)
                {
                    result = tSocket.Host;
                }
                else
                {
                    result = null;
                }
            }
            return result;
        }

        internal static TSocket GetTSocket(this TTransport transport)
        {
            TSocket result;
            if (transport is TSocket)
            {
                result = (transport as TSocket);
            }
            else
            {
                if (transport is TFramedTransport)
                {
                    FieldInfo field = transport.GetType().GetField("transport", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
                    result = (field.GetValue(transport) as TTransport).GetTSocket();
                }
                else
                {
                    if (transport is TBufferedTransport)
                    {
                        PropertyInfo property = transport.GetType().GetProperty("UnderlyingTransport", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);
                        result = (property.GetValue(transport, null) as TTransport).GetTSocket();
                    }
                    else
                    {
                        result = null;
                    }
                }
            }
            return result;
        }

        public static void Close(this Apache.Cassandra.Cassandra.Client client)
        {
            if (client != null)
            {
                try
                {
                    CloseProtocol(client.InputProtocol);
                    CloseProtocol(client.OutputProtocol);
                }
                catch (Exception ex)
                {
                }
            }
        }

        private static void CloseProtocol(TProtocol protocol)
        {
            TTransport transport = protocol.Transport;
            if (transport != null)
            {
                transport.Flush();
                transport.Close();
            }
        }
    }
}